package com.fdb.efp.esb.service.impl.yx;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fdb.efp.esb.common.constant.MsLoanConstant;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.SpringContextUtils;
import com.fdb.efp.esb.service.bo.req.MsYxApproveReqBean;
import com.fdb.efp.esb.service.bo.resp.MsYxApproveRespBean;
import com.fdb.efp.esb.service.client.ESBBeanCreator;
import com.fdb.efp.esb.service.client.impl.BDESBBeanCreator;
import com.fdb.efp.esb.service.impl.esb.AbstractRetryBaseEsbService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.function.Function;

/**
 * 需求编号：xxxxxx<br/>
 * 问题编号：<br/>
 * 功能描述：<br/>
 * 创建时间：2020/6/11 18:09
 *
 * @Author tiankg
 * @Version 1.0
 * @Since 1.0
 */
@Service("msYxApprService")
public class MsYxApproveServiceImpl extends AbstractRetryBaseEsbService<MsYxApproveReqBean, MsYxApproveRespBean> {

    private static Logger log = LoggerFactory.getLogger(MsYxApproveServiceImpl.class);

    // 日志ID
    private static final String LOGGER_ID = "用信风控审批接口";

    /**
     * 流水号关联
     *
     * @param reqBean
     * @return 流水号
     */
    @Override
    protected String applySeq(MsYxApproveReqBean reqBean) {
        if (reqBean.getQryRptsInfArrys().size() > 0) {
            return reqBean.getQryRptsInfArrys().get(0).getAppNo();
        } else {
            return "";
        }
    }

    /**
     * 接口实现需提供将 返回JSON 转换为 Bean 的转换策略
     *
     * @return
     */
    @Override
    protected Function<String, MsYxApproveRespBean> converter() {
        return i -> JSONObject.parseObject(i, new TypeReference<MsYxApproveRespBean>() {
        });
    }

    /**
     * ESBBeanCreator ，用于配置产品机构号，请求头等信息
     *
     * @return
     */
    @Override
    protected ESBBeanCreator beanFactory() {
        return (BDESBBeanCreator) SpringContextUtils.getBean("BDESBBeanCreator");
    }

    /**
     * 对接口返回结果进行处理，并返回包装后的结果
     *
     * @param reqBean
     * @param resBean
     * @return
     * @throws Exception
     */
    @Override
    protected MsYxApproveRespBean postProcess(MsYxApproveReqBean reqBean, MsYxApproveRespBean resBean) throws Exception {
        Optional.
                ofNullable(resBean).
                map(i -> i.getQryRptsInfArry().get(0).getRcvSt()).
                orElseThrow(() -> new ESBException("用信风控审批接口返回为空！"));
        log.debug(LOGGER_ID,"用信风控审批接口进行后续处理，请求参数: " + reqBean + ", 返回结果： " + resBean);
        return resBean;
    }

    /**
     * 各接口的交易码
     *
     * @return
     */
    @Override
    protected String tradeNo() {
//        return ESBTradeNoConstance.ACCESS_RISK;
        return MsLoanConstant.TRADE_NO_30220006;
    }

    /**
     * 各接口的服务场景
     *
     * @return
     */
    @Override
    protected String scene() {
        return MsLoanConstant.SCENE_05;
    }


    /**
     * 执行次数，包括第一次执行
     * 若为3，则第一次执行出错后还会执行2次重试
     *
     * @return
     */
    @Override
    protected Integer retryTimes() {
//        return 3;
        return 4;//与其他接口重试机制保持一致，执行第一次失败后重试3次
    }

    /**
     * 等待时间
     *
     * @return 单位：毫秒
     */
    @Override
    protected Long waitTime() {
        return 5000L;
    }

    /**
     * 等待时间跨度
     * 默认为1，若等待时间为5s，跨度为1，则每次间隔的等待时间为5*1=5s, 5*1=5s, 10*1=5s
     * 若等待时间为5s，跨度为2，则每次间隔的等待时间为5*1=5s, 5*2=10s, 10*2=20s
     * 若等待时间为5s，跨度为3，则每次间隔的等待时间为5*1=5s, 5*3=15s, 10*3=30s
     *
     * @return
     */
    @Override
    protected Long timeSpan() {
        return 1L;
    }

    /**
     * 重试失败后执行的操作
     */
    @Override
    protected void retryFailCallback(MsYxApproveReqBean reqBean) throws ESBException {
        log.error(LOGGER_ID,"用信阶段风控审批接口调用3次失败！流水号："+reqBean.getQryRptsInfArrys().get(0).getAppNo());
//        throw new ESBException("用信阶段风控审批接口调用3次失败");
        throw new ESBException();
    }

    /**
     * 允许自定义成功和失败的判断标准
     *
     * @param res 调用返回值
     * @return
     */
    @Override
    protected boolean isSuccess(MsYxApproveRespBean  res) {

        return "000000".equals(res.getQryRptsInfArry().get(0).getRcvSt());
    }
}
